package cc.rengu.igas.mcps.core.realize.impl;

import cc.rengu.igas.mcps.common.constant.McpsTxnNumConstant;
import cc.rengu.igas.mcps.common.enums.RespCodeEnum;
import cc.rengu.igas.mcps.common.enums.TermStatusEnum;
import cc.rengu.igas.mcps.core.realize.TermService;
import cc.rengu.igas.share.core.model.MchntTermInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.log.RgLog;
import cc.rengu.utility.log.RgLogger;

import java.util.regex.Pattern;

/**
 * 终端相关的业务实现组件
 *
 * @author zhangming
 */
public class TermServiceImpl implements TermService {

    private final RgLogger rglog = RgLog.getLogger(this.getClass().getName());

    @Override
    public MchntTermInfo checkTermInfo(String instId, String mchntNo, String termNo) throws Exception {
        MchntService mchntService = new MchntServiceImpl();
        MchntTermInfo mchntTermInfo = mchntService.getMchntTermInfo(instId, mchntNo, termNo);
        if (null == mchntTermInfo) {
            rglog.error("获取终端信息失败,instId:<{}>,mchntNo:<{}>,termNo:<{}>", instId, mchntNo, termNo);
            throw new BizException(RespCodeEnum.POS_INVALID_TERM.getRespCode(), RespCodeEnum.POS_INVALID_TERM.getRespDesc());
        } else {
            /* 检查终端管理状态 (00-注销 01-正常) */
            if (!TermStatusEnum.NORMAL.getStatus().equals(mchntTermInfo.getTermStatus())) {
                rglog.error("终端状态不合法,status:<{}>", mchntTermInfo.getTermStatus());
                throw new BizException(RespCodeEnum.TERM_STATUS_ABNORMAL.getRespCode(), RespCodeEnum.TERM_STATUS_ABNORMAL.getRespDesc());
            }
            /* 检查终端签到状态(0-不可用 1-可用) */
            XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
            /* 如果是签到交易 并且签到状态为 1-已签到 拒交 */
            if (McpsTxnNumConstant.POS_TERM_SIGN_IN_TXN_NUM.equals(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_NUM)) &&
                    TermStatusEnum.SIGN_NORMAL.getStatus().equals(mchntTermInfo.getTermSignStatus())) {
                rglog.error("终端签到状态已签到,signStatus:<{}>", mchntTermInfo.getTermSignStatus());
                throw new BizException(RespCodeEnum.TERM_ALREADY_SIGNED.getRespCode(), RespCodeEnum.TERM_ALREADY_SIGNED.getRespDesc());
            }
            if (McpsTxnNumConstant.POS_TERM_TMK_DOWNLOAD_TXN_NUM.equals(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_NUM)) ||
                    McpsTxnNumConstant.POS_TERM_SIGN_IN_TXN_NUM.equals(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_NUM)) ||
                    McpsTxnNumConstant.POS_TERM_PARAMLIST_DOWNLOAD_TXN_NUM.equals(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_NUM)) ||
                    TermStatusEnum.SIGN_NORMAL.getStatus().equals(mchntTermInfo.getTermSignStatus())) {
                //终端签到 终端主密钥下载，当前签到状态为不可用，程序继续执行
                return mchntTermInfo;
            } else {
                rglog.error("终端未签到状态,signStatus:<{}>", mchntTermInfo.getTermSignStatus());
                throw new BizException(RespCodeEnum.POS_NOT_SIGN.getRespCode(), RespCodeEnum.POS_NOT_SIGN.getRespDesc());
            }
        }
    }

    /*检查大型智能终端交易*/
    @Override
    public MchntTermInfo checkIlltTermInfo(String instId, String mchntNo, String termNo) throws Exception {
        MchntService mchntService = new MchntServiceImpl();
        MchntTermInfo mchntTermInfo = mchntService.getMchntTermInfo(instId, mchntNo, termNo);
        if (null == mchntTermInfo) {
            rglog.error("获取终端信息失败,instId:<{}>,mchntNo:<{}>,termNo:<{}>", instId, mchntNo, termNo);
            throw new BizException(RespCodeEnum.POS_INVALID_TERM.getRespCode(), RespCodeEnum.POS_INVALID_TERM.getRespDesc());
        } else {
            /* 检查终端管理状态 (00-注销 01-正常)*/
            if (!TermStatusEnum.NORMAL.getStatus().equals(mchntTermInfo.getTermStatus())) {
                rglog.error("终端状态不合法,status:<{}>", mchntTermInfo.getTermStatus());
                throw new BizException(RespCodeEnum.TERM_STATUS_ABNORMAL.getRespCode(), RespCodeEnum.TERM_STATUS_ABNORMAL.getRespDesc());
            }
        }
        return mchntTermInfo;
    }

    @Override
    public void checkTermLocation(String txnLatitude, String txnLongitude, MchntTermInfo mchntTermInfo) throws Exception {
        if (txnLatitude == null || txnLatitude.isEmpty() ||
                txnLongitude == null || txnLongitude.isEmpty()) {
            rglog.info("商户未维护经纬度信息，交易继续");
            return;
        }
        /*如果上送的 经纬度 第一位是非数字 那么删掉*/
        Pattern pattern = Pattern.compile("[0-9]*");
        if (!pattern.matcher(txnLatitude.substring(0, 1)).matches()) {
            txnLatitude = txnLatitude.substring(1, txnLatitude.length() - 1);
        }
        if (!pattern.matcher(txnLongitude.substring(0, 1)).matches()) {
            txnLongitude = txnLongitude.substring(1, txnLongitude.length() - 1);
        }
        double dTxnLongitude = Double.parseDouble(txnLongitude);
        double dTxnLatitude = Double.parseDouble(txnLatitude);
        if (mchntTermInfo.getLongitude() == null || mchntTermInfo.getLongitude().isEmpty() ||
                mchntTermInfo.getLatitude() == null || mchntTermInfo.getLatitude().isEmpty() ||
                mchntTermInfo.getEffectiveRadius() == null || mchntTermInfo.getEffectiveRadius().isEmpty()) {
            rglog.info("商户未维护经纬度信息，不校验");
            return;
        }
        double mchntLongitude = Double.parseDouble(mchntTermInfo.getLongitude());
        rglog.info("mchntLongitude = [{}]", mchntLongitude);
        double mchntLatitude = Double.parseDouble(mchntTermInfo.getLatitude());
        rglog.info("mchntLatitude = [{}]", mchntLatitude);
        double distenceS = distance(dTxnLongitude, dTxnLatitude, mchntLongitude, mchntLatitude);
        rglog.info("distenceS = [{}]", distenceS);
        double limitDistence = Double.parseDouble(mchntTermInfo.getEffectiveRadius()) * 1000;//千米————>米
        if (Math.max(distenceS, limitDistence) == distenceS) {
            rglog.error("POS机已经超出设定使用范围，当前距离商户距离[{}]," + "使用限制距离[{}]", distenceS, limitDistence);
            throw new BizException(RespCodeEnum.MCHNT_OUTOFLOCATION_ERROR.getRespCode(), RespCodeEnum.MCHNT_OUTOFLOCATION_ERROR.getRespDesc());
        }
        rglog.info("，当前距离商户距离[{}],使用限制距离[{}]", distenceS, limitDistence);
    }

    /**
     * 计算地球上任意两点(经纬度)距离
     *
     * @param long1 第一点经度
     * @param lat1  第一点纬度
     * @param long2 第二点经度
     * @param lat2  第二点纬度
     * @return 返回距离 单位：米
     */
    private double distance(double long1, double lat1, double long2, double lat2) {
        double a, b, R;
        R = 6378137; // 地球半径
        lat1 = lat1 * Math.PI / 180.0;
        lat2 = lat2 * Math.PI / 180.0;
        a = lat1 - lat2;
        b = (long1 - long2) * Math.PI / 180.0;
        double d;
        double sa2, sb2;
        sa2 = Math.sin(a / 2.0);
        sb2 = Math.sin(b / 2.0);
        d = 2
                * R
                * Math.asin(Math.sqrt(sa2 * sa2 + Math.cos(lat1)
                * Math.cos(lat2) * sb2 * sb2));
        return d;
    }
}
